package ruru.client.ui.widgets;

import java.util.ArrayList;
import java.util.List;

import ruru.client.RuruDkp;
import ruru.client.backend.RuruUtility;
import ruru.client.backend.rpcWrapper.DkpChangeWrapper;
import ruru.client.backend.rpcWrapper.LiteRaiderWrapper;
import ruru.client.backend.rpcWrapper.RaiderWrapper;
import ruru.client.services.DataService;
import ruru.client.services.DataServiceAsync;
import ruru.client.ui.widgets.sortableTable.ComparableHTML;
import ruru.client.ui.widgets.sortableTable.LastRaidDate;
import ruru.client.ui.widgets.sortableTable.Sortable;
import ruru.client.ui.widgets.sortableTable.SortableTable;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HTMLTable.ColumnFormatter;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;

public class PersonalDkpWidget extends Composite {
	private VerticalPanel vp;
	private MenuBar menu;
	private boolean initialized = false;
	VerticalPanel tableHolder;
	// Label loadingLabel = new Label("Loading...");
	HTML loadingImage = new HTML("<img src='images/loading.gif'>");
	HorizontalPanel menuHp;
	MenuBar classMenu;
	MenuItem choose;
	List classContainers;
	List menuBarList;
	boolean calledByRuruDkp = false;

	/**
	 * A private class with public member variables that include the className and a list of Raider object members.
	 * 
	 * @author zane.tian@gmail.com
	 */
	private class ClassContainer {
		String className;
		List members;

		public ClassContainer(String className, List members) {
			this.className = className;
			this.members = members;
		}
	}

	public PersonalDkpWidget() {
		vp = new VerticalPanel();
		menu = new MenuBar();

		tableHolder = new VerticalPanel();
		loadingImage.addStyleName("raid-loading-label");
		loadingImage.addStyleName("center-loading-label");
		initWidget(vp);
	}

	public void load(List liteRaiderWrappers) {
		if(!initialized) {
			classContainers = new ArrayList();
			classContainers.add(new ClassContainer("druid", new ArrayList()));
			classContainers.add(new ClassContainer("hunter", new ArrayList()));
			classContainers.add(new ClassContainer("mage", new ArrayList()));
			classContainers.add(new ClassContainer("paladin", new ArrayList()));
			classContainers.add(new ClassContainer("rogue", new ArrayList()));
			classContainers.add(new ClassContainer("warlock", new ArrayList()));
			classContainers.add(new ClassContainer("priest", new ArrayList()));
			classContainers.add(new ClassContainer("shaman", new ArrayList()));
			classContainers.add(new ClassContainer("warrior", new ArrayList()));

			for(int i = 0; i < liteRaiderWrappers.size(); i++) {
				LiteRaiderWrapper raider = (LiteRaiderWrapper) liteRaiderWrappers.get(i);

				String raidClass = raider.getWowClass();
				if(!raider.isRetired()) {
					for(int j = 0; j < classContainers.size(); j++) {
						ClassContainer c = (ClassContainer) classContainers.get(j);
						if(raidClass.equals(c.className)) {
							c.members.add(raider);
						}
					}
				}
			}

			/* menuBarList is the list of class menubars (priest, rogue, shaman, etc) */
			menuBarList = new ArrayList();
			for(int i = 0; i < classContainers.size(); i++) {
				ClassContainer c = (ClassContainer) classContainers.get(i);
				MenuBar classBar = new MenuBar(true);
				for(int j = 0; j < c.members.size(); j++) {
					final String name = ((LiteRaiderWrapper) c.members.get(j)).getName();
					final String raidClass = ((LiteRaiderWrapper) c.members.get(j)).getWowClass();
					final String capitalName = RuruUtility.capFirstLetter(name);
					classBar.addItem("<div class='" + c.className + "'>" + capitalName + "</div>", true, new Command() {
						public void execute() {
							tableHolder.clear();
							vp.remove(tableHolder);
							vp.add(loadingImage);
							System.out.println("raiderWrapper " + name + " beginning to load: "
									+ (System.currentTimeMillis() - RuruDkp.start) + "ms");

							// choose.setHTML("<div class='menu_arrowd lightLabelColor'>Choose&nbsp;a&nbsp;Raider:&nbsp;<span
							// class='"
							// + raidClass + "'>" + capitalName + "</span></div>");
							getRaiderWrapperByName(name, raidClass, capitalName);
						}
					});

					classBar.addStyleName("lowerMenuBackground");
				}
				menuBarList.add(classBar);
			}

			menu.setStyleName("border");

			MenuBar menu = new MenuBar();
			menu.addStyleName("mainMenuBackground");

			menu.setAutoOpen(true);
			classMenu = new MenuBar(true);
			classMenu.addStyleName("lowerMenuBackground");
			classMenu.addStyleName("classMenuMargin");

			for(int i = 0; i < classContainers.size(); i++) {
				ClassContainer c = (ClassContainer) classContainers.get(i);
				classMenu.addItem("<div class='" + c.className + " menu_arrow'>" + RuruUtility.capFirstLetter(c.className)
						+ "</div>", true, (MenuBar) menuBarList.get(i));
			}

			choose = new MenuItem("<div class='menu_arrowd lightLabelColor'>Choose&nbsp;a&nbsp;Raider</div>", true,
					classMenu);
			menu.addItem(choose);
			menuHp = new HorizontalPanel();
			menuHp.add(menu);
			vp.add(menuHp);
			vp.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
			vp.addStyleName("personal-dkp-widget");

			initialized = true;
		}
	}

	/**
	 * Called from Rurudkp.java through a mouselistener in StandingsWidget.
	 * 
	 * @param name
	 * @param raidClass
	 */
	public void openRaiderHistoryPage(String name, String raidClass) {
		if(!initialized) {
			System.err.println("openRaiderHistoryPage() called before personalDkpWidget was initialized");
		}
		tableHolder.clear();
		vp.remove(tableHolder);
		vp.add(loadingImage);
		System.out.println("raiderWrapper " + name + " beginning to load: "
				+ (System.currentTimeMillis() - RuruDkp.start) + "ms");

		getRaiderWrapperByName(name, raidClass, RuruUtility.capFirstLetter(name));
	}

	public SortableTable createTable(List changes, int lastN) {
		SortableTable result = new SortableTable();
		result.setWidth("100%");
		result.addColumnHeader("Description", 0);
		result.addColumnHeader("Value", 1);
		result.addColumnHeader("Date", 2);

		int count = 0;
		// guard against new raiders having less than lastN changes
		int lowerBound = changes.size() - lastN;
		if(lowerBound < 0) {
			lowerBound = 0;
		}
		for(int i = changes.size() - 1; i >= lowerBound; i--) {
			DkpChangeWrapper wrapper = (DkpChangeWrapper) changes.get(i);

			if(wrapper.getDescription().substring(0, 6).equals("Item: ")) {
				result.setValue(count + 1, 0, new ItemLink(wrapper.getDescription().substring(6)));
			} else {
				result.setValue(count + 1, 0, wrapper.getDescription());
			}

			ComparableHTML d = new ComparableHTML(RuruUtility.twoDecimals(Math.abs(wrapper.getValue())));

			if(wrapper.getValue() <= 0) {
				d.addStyleName("dkp-expenditure");
			} else {
				d.addStyleName("dkp-income");
			}
			d.addStyleName("text-align-right");
			result.setValue(count + 1, 1, d);

			LastRaidDate cell = new LastRaidDate(wrapper.getDate());
			result.setValue(count + 1, 2, cell);
			count++;
		}

		CellFormatter cellFormatter = result.getCellFormatter();

		for(int k = 0; k < count + 1; k++) {
			for(int j = 0; j < 3; j++) {
				cellFormatter = result.getCellFormatter();
				cellFormatter.addStyleName(k, j, "sortable-table-cell");

				if(j == 2) {
					cellFormatter.addStyleName(k, j, "text-align-right");
				}
			}
		}

		/* Set header text-alignments */
		cellFormatter.addStyleName(0, 1, "text-align-right");
		cellFormatter.addStyleName(0, 2, "text-align-right");

		result.addStyleName("sortable-table");
		result.setCellSpacing(0);
		ColumnFormatter colForm = result.getColumnFormatter();
		colForm.setWidth(0, "70%");
		colForm.setWidth(1, "12%");
		colForm.setWidth(2, "28%");

		// Set Style Name for the header
		RowFormatter rowFormatter = result.getRowFormatter();
		rowFormatter.addStyleName(0, "standings-tableHeader");

		System.out.println((System.currentTimeMillis() - RuruDkp.start) + "ms");

		result.forceSort(2, Sortable.SORT_DESC);
		result.addStyleName("history-table-border");
		return result;
	}

	public void getRaiderWrapperByName(String name, String raidClass, String capitalName) {
		choose.setHTML("<div class='menu_arrowd lightLabelColor'>Choose&nbsp;a&nbsp;Raider:&nbsp;<span class='"
				+ raidClass + "'>" + capitalName + "</span></div>");

		DataServiceAsync ds = (DataServiceAsync) GWT.create(DataService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) ds;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "/DataService";
		endpoint.setServiceEntryPoint(moduleRelativeURL);
		AsyncCallback callback = new AsyncCallback() {

			/**/
			public void onSuccess(Object result) {
				RaiderWrapper raiderWrapper = (RaiderWrapper) result;
				System.out.println("raiderWrapper " + raiderWrapper.getName() + " loaded in client: "
						+ (System.currentTimeMillis() - RuruDkp.start) + "ms");

				// stuff all attendance dkp awards into a list
				List attendance = new ArrayList();
				for(int i = 0; i < raiderWrapper.getDkpChangeWrappers().size(); i++) {
					DkpChangeWrapper wrapper = (DkpChangeWrapper) raiderWrapper.getDkpChangeWrappers().get(i);
					if(wrapper.getDescription().substring(0, 6).equals("Item: ")) {
						// do nothing
					} else {
						attendance.add(wrapper);
					}
				}

				// stuff all loot awards into a list
				List loot = new ArrayList();
				for(int i = 0; i < raiderWrapper.getDkpChangeWrappers().size(); i++) {
					DkpChangeWrapper wrapper = (DkpChangeWrapper) raiderWrapper.getDkpChangeWrappers().get(i);
					if(wrapper.getDescription().substring(0, 6).equals("Item: ")) {
						loot.add(wrapper);
					}
				}

				// calculate how much dkp this raider has spent
				// this does not include dkp cap restrictions, noted by "Cap Restriction" in the description
				double spent = 0;
				for(int i = 0; i < loot.size(); i++) {
					DkpChangeWrapper wrapper = (DkpChangeWrapper) loot.get(i);
					spent -= wrapper.getValue();
				}

				// calculate how much dkp this raider has earned through attendance
				double earned = 0;
				for(int i = 0; i < attendance.size(); i++) {
					DkpChangeWrapper wrapper = (DkpChangeWrapper) attendance.get(i);
					earned += wrapper.getValue();
				}
				
				
				
				double pointsLostToCap = 0;
				for(int i = 0; i < attendance.size(); i++) {
					DkpChangeWrapper wrapper = (DkpChangeWrapper) attendance.get(i);
					if(wrapper.getDescription().equals("Cap Restriction")) {
						pointsLostToCap -= wrapper.getValue();
					}
				}
				spent -= pointsLostToCap;

				HTML dkpHTML = new HTML("<span class='lightLabelColor'> Current DKP: </span>"
						+ RuruUtility.twoDecimals(raiderWrapper.getDkp()));
				HTML earnedHTML = new HTML("<span class='lightLabelColor'> Total DKP Earned: </span>"
						+ RuruUtility.twoDecimals(earned));
				HTML spentHTML = new HTML("<span class='lightLabelColor'> Total DKP Spent: </span>"
						+ RuruUtility.twoDecimals(spent));
				HTML capHTML = new HTML("<span class='lightLabelColor'> Total DKP Lost Due to Cap: </span>"
						+ RuruUtility.twoDecimals(pointsLostToCap));
				
				tableHolder.add(dkpHTML);
				tableHolder.add(earnedHTML);
				tableHolder.add(spentHTML);
				tableHolder.add(capHTML);

				Label attendanceLabel = new Label("Attendance Over Last 7 Raids:");
				attendanceLabel.addStyleName("personalDkp-tableLabel-padding");
				attendanceLabel.addStyleName("lightLabelColor");

				Label lootLabel = new Label("Item Purchase History:");
				lootLabel.addStyleName("personalDkp-tableLabel-padding");
				lootLabel.addStyleName("lightLabelColor");

				VerticalPanel attendanceHolder = new VerticalPanel();
				attendanceHolder.setWidth("100%");
				attendanceHolder.add(createTable(attendance, 7));

				VerticalPanel lootHolder = new VerticalPanel();
				lootHolder.add(createTable(loot, loot.size()));
				lootHolder.setWidth("100%");

				tableHolder.add(attendanceLabel);
				tableHolder.add(attendanceHolder);
				tableHolder.add(lootLabel);
				tableHolder.add(lootHolder);

				attendanceHolder.addStyleName("history-table-holder");
				lootHolder.addStyleName("history-table-holder");

				tableHolder.setWidth("100%");
				tableHolder.addStyleName("personalDkp-tableHolder");

				vp.remove(loadingImage);
				vp.add(tableHolder);
			}

			/**/

			public void onFailure(Throwable caught) {
				System.out.println("in client: getRaiderWrapperByName failure");
				caught.printStackTrace();
			}
		};
		ds.getRaiderWrapperByName(name, callback);
	}
}